// These are meant to be typed into the REPL. You can also run
// scala -Xnojline < repl-session.scala to run them all at once.
/**
  * 3.7 异常
  * 当碰到异常情况时，方法抛出一个异常，终止方法本身的执行，异常传
  * 递到其调用者，调用者可以处理该异常，也可以升级到它的调用者。运行系
  * 统会一直这样升级异常，直到有调用者能处理它。 如果一直没有处理，则终
  * 止整个程序。
  * Scala 的异常的工作机制和 Java 一样， 但是 Scala 没有“受检”异常，你
  * 不需要声明说函数或者方法可能会抛出某种异常。 受检异常在编译器被检
  * 查， java 必须声明方法所会抛出的异常类型。大数据技术之 Scala 程序设计解析
  * 25
  * 抛出异常：用 throw 关键字，抛出一个异常对象。所有异常都是
  * Throwable 的子类型。 throw 表达式是有类型的， 就是 Nothing，因为 Nothing
  * 是所有类型的子类型，所以 throw 表达式可以用在需要类型的地方。
  *
  * ／／并不像 Java 代码那样，需要声明方法会抛出异常，这给程序员省去理论很多烦恼。
  * def divide(x: Int, y: Int): Int = {
  * if (y == 0) throw new Exception("Divide by zero")
  * else x / y
  * }
  * 捕捉异常：
  * 在 Scala 里，借用了模式匹配的思想来做异常的匹配，因此，在 catch 的
  * 代码里，是一系列 case 字句。
  * 异常捕捉的机制与其他语言中一样，如果有异常发生， catch 字句是按次
  * 序捕捉的。因此，在 catch 字句中，越具体的异常越要靠前，越普遍的异常越
  * 靠后。 如果抛出的异常不在 catch 字句中，该异常则无法处理，会被升级到
  * 调用者处。
  * 异常捕获通常采用模式匹配的语法：
  *
  * try {
  * process(in)
  * } catch {
  * case ex: IOException => println(ex)
  * } finally {
  * in.close()}
  * finally 字句用于执行不管是正常处理还是有异常发生时都需要执行的步
  * 骤，一般用于对象的清理工作。
  * 注： 1、 Throw 的类型为 Nothing， 存在 exception 的 if 语句类型返回类型。
  */

import java.io.IOException

import scala.math._
// 异常的为Nothing
def root(x: Double) = 
  if (x >= 0) { sqrt(x) 
  } else throw new IllegalArgumentException("x should not be negative")

try {
  println(root(4))
  println(root(-4))
} catch {
  case e: Exception => println(e)
} finally {
  println("finally....")
}
